﻿<script setup lang="ts" name="UploadSource">
import { errorMessage } from '@/utils/message'
import { transformI18n } from '@/plugins/i18n'
import { base } from '@/api/public'

const emit = defineEmits(['change', 'delete'])

const props = defineProps({
  width: {
    type: [String, Number],
    default: '160px'
  },
  value: { type: String },
  text: { type: Object }
})

const initInfo = ref({
  isPreview: false,
  list: props.value ? [props.value] : [],
  type: '',
  fileTypeArr: ['7z', 'ai', 'cdr', 'class', 'css', 'csv', 'doc', 'dockerfile', 'docx', 'exe', 'gitignore', 'html', 'iso', 'jar', 'java', 'js', 'json', 'md', 'pdf', 'ppt', 'pptx', 'pr', 'psd', 'py', 'rar', 'sql', 'svg', 'txt', 'xls', 'xlsx', 'xml', 'yml', 'zip']
})

watch(
  () => props.value,
  (val) => {
    const index = val.lastIndexOf('.')
    const type = val.substring(index + 1)
    if (type === 'jpg' || type === 'jpeg' || type === 'png' || type === 'gif' || type === 'bmp') {
      initInfo.value.type = 'image'
    } else if (type === 'mp4' || type === 'rmvb' || type === 'avi' || type === 'ts') {
      initInfo.value.type = 'video'
    } else if (type === 'mp3') {
      initInfo.value.type = 'audio'
    } else {
      initInfo.value.type = type
    }
    initInfo.value.list = [val]
  },
  {
    immediate: true
  }
)

const newwidth = computed(() => `${props.width}`.replace(/px/, '') + 'px')

// 文件上传前置方法
const beforeUploadSource = (file) => {
  if (props.text.size > 0) {
    const isMaxSize = file.size / 1024 < props.text.size
    if (!isMaxSize) {
      errorMessage(transformI18n('page.' + props.text.errorMaxSize))
    }
    return isMaxSize
  }
}

// 自定义文件上传方法
const uploadSourceHandler = async (param: any) => {
  const formData = new FormData()
  formData.append('file', param.file)
  await base.upload(formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    config: { showLoading: false, cancelRepeatDisabled: true }
  }).then((res: any) => {
    if (res && res.status) {
      emit('change', res.data)
    }
  })
}

// 删除
const deleteCover = () => {
  emit('delete')
}

// 预览
const previewCover = () => {
  initInfo.value.isPreview = true
}

// 关闭预览
const closePreview = () => {
  initInfo.value.isPreview = false
}
</script>

<template>
  <div class="upload-source">
    <div v-if="props.value" class="source-preview">
      <div class="mask">
        <svg-icon v-if="initInfo.type === 'image'" icon="ri:eye-line" size="18" :title="$t('buttons.buttonPreview')" @click="previewCover"></svg-icon>
        <el-upload action="" :accept="props.text.accept" :show-file-list="false" :before-upload="beforeUploadSource" :http-request="uploadSourceHandler">
          <svg-icon icon="ri:exchange-line" size="18" :title="$t('buttons.' + props.text.title)"></svg-icon>
        </el-upload>
        <svg-icon icon="ri:delete-bin-5-line" size="18" :title="$t('buttons.buttonRemove')" @click="deleteCover"></svg-icon>
      </div>
      <template v-if="initInfo.type === 'image'">
        <el-image :src="props.value" fit="fill"></el-image>
        <el-image-viewer v-if="initInfo.isPreview" :url-list="initInfo.list" :initial-index="0" :hide-on-click-modal="true" @close="closePreview"></el-image-viewer>
      </template>
      <svg-icon v-else-if="initInfo.type === 'video'" icon="ci:filetype-video" size="64"></svg-icon>
      <svg-icon v-else-if="initInfo.type === 'audio'" icon="ci:filetype-audio" size="64"></svg-icon>
      <template v-else>
        <svg-icon v-if="initInfo.fileTypeArr.includes(initInfo.type)" :icon="'ci:filetype-' + initInfo.type" size="64"></svg-icon>
        <svg-icon v-else icon="ci:filetype-unknown" size="64"></svg-icon>
      </template>
    </div>
    <el-upload v-else class="new-source" action="" :accept="props.text.accept" :show-file-list="false" :before-upload="beforeUploadSource" :http-request="uploadSourceHandler">
      <svg-icon icon="ep:plus" size="28" color=""></svg-icon>
    </el-upload>
    <div v-if="props.text.size > 0" class="upload-tips">
      <p v-html="$t('page.' + props.text.helpText)"></p>
    </div>
  </div>
</template>

<style scoped lang="scss">
.upload-source{
  display: flex;
  flex: 1;
  padding: 6px;

  .source-preview{
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: v-bind(newwidth);
    height: v-bind(newwidth);
    overflow: hidden;
    background-color: var(--el-fill-color-lighter);
    border: 1px solid var(--el-border-color-darker);
    border-radius: 6px;

    &:hover {
      .mask{
        visibility: visible;
        opacity: 1;
      }
    }

    .mask{
      position: absolute;
      top: 0;
      left: 0;
      z-index: 10;
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 100%;
      background: rgba(0, 0, 0, 0.5);
      visibility: hidden;
      opacity: 0;
      transition: all 0.3s;

      > div{
        line-height: 0;
      }

      .el-icon{
        margin: 0 6px;
        color: #ffffff;
        font-size: 24px!important;
        cursor: pointer;
        transition: all 0.3s;

        &:hover{
          font-size: 32px!important;
        }
      }
    }

    .el-image, .el-image :deep(.el-image__inner){
      max-width: calc(v-bind(newwidth) - 2px);
      max-height: calc(v-bind(newwidth) - 2px);
    }
  }

  .new-source{
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: v-bind(newwidth);
    height: v-bind(newwidth);
    background-color: var(--el-fill-color-lighter);
    border: 1px dashed var(--el-border-color-darker);
    border-radius: 6px;
    cursor: pointer;

    &:hover {
      border-color: var(--el-color-primary);
    }

    :deep(.el-upload) {
      flex: 1;
      height: 100%;
    }
  }

  .upload-tips{
    display: flex;
    flex: 1;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    padding-left: 10px;

    p {
      color: var(--el-text-color-secondary);
      font-size: 12px;
      line-height: 24px;
    }
  }
}
</style>
